(*************************************************** Ant Movie Catalog importation script www.antp.be/software/moviecatalog/ [Infos] Authors=scorpion7552 (scripts originaux: Antoine Potten (MrCinéma) et Danone-Kid (Cinéfil)) Title=Monsieur Cinéma Description=infos de MrCinéma - mode normal/batch: voir l'onglet Commentaires Site=http://cinema.tiscali.fr Language=FR Version=5.2 Requires=3.5.0 Comments=mode batch: 2 modes possibles: d'après l'url mémorisée (MrCinéma) ou d'après le nom du film + réalisateur (résultats non garantis!)|N'oubliez pas de sauvegarder votre base actuelle avant de lancer le mode batch|Conseils: sélectionnez un nombre raisonnable de films et triez la liste des films par numéros|à la fin de chaque mise à jour, un fichier log est créé (informations et erreurs - attention ce fichier est recréé à chaque lancement de ce script) License=This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GetInfo=1 [Options] Image=1|1|0=aucune image|1=image MrCinéma seule|2=image Cinéfil seule|3=toutes les images Histoire=0|0|0=résumé (s'il existe, sinon histoire complète)|1=histoire complète Anecdote=0|0|0=pas d'anecdote|1=anecdote à la suite de l'avis de la rédaction (Commentaires) Générique=0|0|0=générique réduit|1=générique complet FormatTitre=0|0|0=laisser les titres des films tels quels|1=tout en minuscules|2=tout en majuscules|3=1ère lettre en majuscule le reste en minuscules|4=toutes les 1ères lettres en majuscules Mode=0|0|0=mode normal|1=mode batch (url)|2=mode batch (nom + réalisateur) ***************************************************) // nécessite les modules suivants // StringUtils1.pas, StringUtils7552.pas et MrCinemaCinefilCommon.pas program MonsieurCinema; uses MrCinemaCinefilCommon; const MrCinemaUrl = 'http://cinema.tiscali.fr/'; MrCinemaUrlFilm = MrCinemaUrl + 'fichefilm.aspx'; { recherche: films classés par titres (on peut aussi faire &filtre=annee)} MrCinemaUrlLook = MrCinemaUrl + 'recherche.aspx?file=http&filtre=titre&keys='; var viewstate, idhistoire, idavis, idgenerique, idanecdote, annee: string; ImportPicture: integer; //------------------------------------------------------------------------------ // recherche du film // MovieName = nom du film cherché (tel que saisi, cad non formaté) //------------------------------------------------------------------------------ procedure AnalyzePageMrCinema; var Address, Page, Value, PageFilm, urlFilm: String; pagenum, i: integer; memo: TStringList; begin pagenum := 0; // compteur de pages // init adresse 1ère recherche Address := MrCinemaUrlLook+FormatMovieName2(MovieName); repeat PageNext := ''; PagePrev := ''; // traitement page courante // attention aux positionnements: les textes sont au format UTF-8 pagenum := pagenum + 1; FormatUTF8 := 1; memoAdr := TStringList.Create; // init listes de mémo memoTxt := TStringList.Create; Page := GetPage(UrlEncode(Address)); if debug then DumpPage(debugrep+'choixMrCinema'+IntToStr(pagenum)+'.txt', Page); // debug Page := TextAfter(Page, 'Vous effectuez une recherche sur'); if Page = '' then begin LogMessage('MrCinéma: erreur lecture page de recherche '+IntToStr(pagenum)); memoAdr.Free; memoTxt.Free; exit; end; // c'est ici qu'il faudrait mémoriser PagePrev/PageNext // pour l'instant il n'y en pas, mais c'est pas une raison pour ne pas le prévoir ... if PagePrev <> '' then begin memoAdr.Add(PagePrev); memoTxt.Add('<<< page précédente'); end; // mémo des films de cette page (if any) urlFilm := ' 0 then begin // mode batch : recherche du meilleur poids pour les films de cette page LookBest(mrcinema_id); if (bestpoids = maxcount) or (PageNext = '') or (pagenum > pagemax) then // poids max ou pas de page next ou max pages lues: on arrete begin if bestpoids > 0 then // on a trouvé quelque chose begin if bestpoids < maxcount then // infos partielles LogMessage('MrCinéma: '+looktxt+' retenu '+besttxt+' (poids='+IntToStr(bestpoids)+')'); AnalyzeMoviePageMrCinema(bestadr); // page film end else LogMessage('MrCinéma: pas de correspondance pour '+looktxt); break; // on sort end else // sinon, on va chercher s'il y a mieux mieux dans pagenext Address := PageNext; end else // mode normal begin Address := SelectMovie('Films (Monsieur Cinéma)'); if Address <> '' then begin if (Address <> PageNext) and (Address <> PagePrev) then begin AnalyzeMoviePageMrCinema(Address); // page film break; // on sort end; end else LogMessage('MrCinéma: aucun film sélectionné'); end; until (Address = ''); memoAdr.Free; memoTxt.Free; end; //------------------------------------------------------------------------------ // analyse de la page du film //------------------------------------------------------------------------------ procedure AnalyzeMoviePageMrCinema(Address: string); var Fullpage, PageEssentiel, PageHistoire, PageAvis, PageGenerique, PageAnecdote: string; Value, Value2, titreo, titret, realisateur, producteur, duree, acteurs: string; memo: TStringList; i: integer; begin // attention aux positionnements: les textes sont au format UTF-8 FormatUTF8 := 1; annee := ''; Fullpage := GetPage(Address); // charge la 1ère page ("l'essentiel") if debug then DumpPage(debugrep+'filmMrCinema.txt', Fullpage); // debug if Pos('L''essentiel', Fullpage) = 0 then Begin LogMessage('MrCinéma: erreur lecture page essentiel'); exit; end; filmok := True; // ça y est, c'est bon SetField(fieldURL, Address); GetSubParms(Fullpage); // récupère les identifiants des pages secondaires // infos utiles de la page "essentiel" PageEssentiel := TextBetween(Fullpage, '', ''); //********** générique //*** les infos du générique sont plus ou moins valorisées //*** quant à l'année, elle peut être vraiment n'importe où !!! // si générique complet demandé if (GetOption('Générique') = 1) and (idgenerique <> '') then begin PageGenerique := GetSubPage(Address, idgenerique, 'generique'); // titre Original/traduit titret := TextBetween(PageGenerique, '', ''); titreo := TextBetween(PageGenerique, '', ''); // séparer les 2 tables Value := TextBetween(PageGenerique, '', '
'); // infos générales acteurs := TextBetween(RemainingText, '', '
'); // rôles/acteurs // acteurs acteurs := FormatTable(acteurs, 'nocont'); // ne pas recoller les lignes acteurs := StringReplace(acteurs, sepchar2, '-'); // infos générales Value := FormatTable(Value, ''); // recoller les lignes // réalisateur (et année) realisateur := ExtractInfo(Value, 'réalis'); // réalisation, réalisateur, réalisé,... ExtrAnnee(realisateur); // producteur (parfois c'est "réalisé et produit par machin (année)" ) producteur := ExtractInfo(Value, 'produ'); // produit, production, ... ExtrAnnee(producteur); // durée duree := ExtractInfo(Value, 'durée'); // durée duree := FormatText(TextBefore(duree, 'minutes', '')); end; // si pas de générique complet ou champs non trouvés, on essaie dans la page 'essentiel' // titre original if titret = '' then titret := TextBetween(PageEssentiel, '', ''); // titre traduit (et année) Value := TextBetween(PageEssentiel, '', ''); ExtrAnnee(Value); // 5.1: l'année est maintenant ici if titreo = '' then titreo := Value; // réalisateur Value := TextAfter(PageEssentiel, '
'); if realisateur = '' then realisateur := TextBetween(Value, 'de', '
'); // année (anciennes fiches) if annee = '' then begin annee := TextBetween(Value, '', 'avec'); annee := TextBetween(annee, '(', ')'); end; // acteurs if acteurs = '' then begin acteurs := TextBetween(Value, 'avec', '', ''); // résumé if (idhistoire <> '') and ((Value = '') or (GetOption('Histoire') = 1) or (Pos('>Lire la suite<', Value) > 0)) then begin // 5.1 pas de résumé ou début de histoire complète ou histoire complète demandée PageHistoire := GetSubPage(Address, idhistoire, 'histoire'); Value := TextBetween(PageHistoire, '
', '
'); end; SetField(fieldDescription, FormatText(Value)); //********** avis de la rédaction, note (peuvent être dans la page "essentiel") + anecdote Value := ''; PageAvis := TextAfter(Fullpage, 'L''avis de la rédaction' ); if (PageAvis = '') and (idavis <> '') then // avis sur autre page PageAvis := GetSubPage(Address, idavis, 'avis'); Value := FormatText(TextBetween(PageAvis, '

', '

')); // Value = avis de la rédaction: garder pour compléter avec l'anecdote Value2 := TextBetween(PageAvis, 'Aucun avis de la redaction.', PageAvis) > 0) and (Value2 = '0') then Value2 := ''; // pas d'avis et img = 0redac.gif alors ignorer if Value2 <> '' then Value2 := IntToStr(StrToInt(Value2, 0) * 2); // note = 2 * x SetField(fieldRating, Value2); // on ajoute l'anecdote si demandé et existant if (GetOption('Anecdote') = 1) and (idanecdote <> '') then begin PageAnecdote := GetSubPage(Address, idanecdote, 'anecdote'); Value2 := FormatText(TextBetween(PageAnecdote, '
', '
')); if Value2 <> '' then begin if Value <> '' then Value := Value + crlf + crlf; Value := Value + 'Anecdote' + crlf + Value2; end; end; SetField(fieldComments, Value); //********** hors zone dynamique // 5.2 changement de certains tags Value2 := TextBetween(Fullpage, '', '
'); // genre Value := FormatText(TextBetween(Value2, 'Genre', '')); SetField(fieldCategory, Value); // durée (sauf si déjà fait) if duree = '' then begin // format hh:mm:ss à transformer en minutes duree := FormatText(TextBetween(Value2, 'Durée', '')); if duree <> '' then // format hh:mm:ss duree := IntToStr(StrToInt(Left(duree, 2), 0) * 60 + StrToInt(Copy(duree, 4, 2), 0)); end; SetField(fieldLength, duree); // on range maintenant // pays Value := FormatText(TextBetween(Value2, 'Pays ', '')); if Value <> '' then begin // pas toujours très cohérents les noms de pays... Value := StringReplace(Value, '.', ''); Value := StringReplace(Value, ',', ''); Value := StringReplace(Value, '/', ' '); Value := StringReplace(Value, '-' ,' '); Value := CompactString(Value, ''); Value := TranslateText(Value, 4); Value := StringReplace(Value, 'Usa', 'Etats-Unis'); Value := StringReplace(Value, 'Etats Unis', 'Etats-Unis'); Value := StringReplace(Value, 'Grande Bretagne', 'Grande-Bretagne'); Value := StringReplace(Value, 'Nouvelle Zélande', 'Nouvelle-Zélande'); // tri memo := TStringList.Create; memo.Text := StringReplace(Value, ' ', crlf); SortList(memo); Value := Trim(StringReplace(memo.Text, crlf, ' ')); memo.Free; end; SetField(fieldCountry, Value); //********** image si demandée (rappel: ImportPicture = 0 si not CanSetPicture) if (ImportPicture = 1) or (ImportPicture = 3) then begin Value := TextBetween(Value2, ' '' then GetPicture(Value); end; end; //------------------------------------------------------------------------------ // extraction de l'année dans une chaine (texte_à_garder (année) ) //------------------------------------------------------------------------------ procedure ExtrAnnee(var str: string); var i: integer; begin i := LastPos('(1', str); // (1xxx ou (2xxx ça devrait suffire !!! if i = 0 then i := LastPos('(2', str); if i > 0 then // année trouvée begin if annee = '' then annee := Copy(str, i+1, 4); str := Left(str, i -1); // chaine initiale sans l'année end; end; //------------------------------------------------------------------------------ // formatage du nom du film //------------------------------------------------------------------------------ function FormatMovieName2(str: string) :string; var i, j: integer; begin // une petite édition avant de formater str := StringReplace(str, ' & ', ' et '); str := StringReplace(str, ' & ', ' et '); // MrCinéma traite bizarrement SES titres s'ils contiennent une virgule ou deux points // exemple "2001 l'odyssée de l'espace" connu sous "2001 : l'odyssée de l'espace" // il faut rentrer soit "2001" , soit "l'odyssee de l'espace" // mais pas les 2 (il ne rend rien dans ce cas: oui, c'est bien bizarre...) // donc on s'arrête aussi au premier de ces caractères (mais ça règle pas tout) i := Pos(',', str); j := Pos(':', str); if (i <> 0) or (j <> 0) then // au moins 1 de trouvé begin if i = 0 then i := j else begin if (j <> 0) and (i > j) then i := j; end; str := Left(str, i -1); end; result := FormatMovieName(str); end; //------------------------------------------------------------------------------ // formatage d'une table (générique) //------------------------------------------------------------------------------ function FormatTable(str1, flag: string) :string; var sepcel: string; begin // structure table // = début de ligne // texte = 1 cellule // .................... autres cellules // = fin de ligne str1 := StringReplace(str1, crlf, ''); // supprimer les crlf str1 := StringReplace(str1, '', sepchar2); // cellule du 'milieu' str1 := StringReplace(str1, 'texte // crlf+sepchar1+sepchar2 = texte // et le remplacer par crlf (à priori seuls cas possibles) sepcel := crlf+sepchar1+sepchar2; if Pos(sepcel, str1) <> 1 then sepcel := crlf+sepchar1; str1 := StringReplace(str1, sepcel, crlf); // s'il reste des crlf+sepchar2+sepchar2 ou crlf+sepchar2, il s'agit de continuations de lignes // recoller les lignes si demandé if flag = 'nocont' then sepcel := crlf // on recolle pas else sepcel := ' '; // 1 blanc pour ne pas coller au précédent str1 := StringReplace(str1, crlf+sepchar2+sepchar2, sepcel); str1 := StringReplace(str1, crlf+sepchar2, sepcel); // str1 := StringReplace(str1, sepchar2+sepchar2, sepchar2); // supprimer les cellules vides str1 := StringReplace(str1, sepchar2+sepchar2, sepchar2); // oui, c'est voulu str1 := StringReplace(str1, sepchar2, ' '+sepchar2+' '); // decoller les séparateurs du texte str1 := StringReplace(str1, sepchar1, ''); // et celui qui reste result := str1; // suite du formatage dans FormatText end; //------------------------------------------------------------------------------ // extraction des infos des tables MrCinéma //------------------------------------------------------------------------------ Function ExtractInfo(str1, from: string) :string; var i: integer; begin // si pas de séparateur de champs (sepchar2), alors on prend le mot suivant (anciennes définitions) // d'où la recherche sur des mots 'incomplets' (et en plus, ça permet de couvrir plus de cas...) // rappel: le mot cherché (from) peut contenir des majuscules result := ''; i := Pos(AnsiLowerCase(from), AnsiLowerCase(str1)); if i = 0 then exit; // from non trouvé str1 := Copy(str1, i + Length(from), Length(str1)); i := Pos(crlf, str1); if i > 0 then // si pas de crlf, prendre tout str1 := Left(str1, i-1); i := Pos(sepchar2, str1); if i = 0 then i := Pos(' ', str1); result := Copy(str1, i +1, length(str1)); end; //------------------------------------------------------------------------------ // récupération des identifiants 'sous-pages' // GetSubParms(page) //------------------------------------------------------------------------------ procedure GetSubParms(s: string); var Value: string; i: integer; begin // infos utiles // 5.2 les url ont la bougeotte donc ne pas pré-déterminer l'ordre Value := TextBetween(s, 'L''essentiel', ''); if Pos('doPostBack', Value) > 0 then begin // formulaire et PostPage (ancienne méthode) // à garder tant que la fonction doPostBack est définie dans la page (on ne sait jamais...) // récupère le paramètre VIEWSTATE (ident de session) viewstate := TextBetween(s, 'name="__VIEWSTATE"', '/>'); viewstate := TextBetween(viewstate, 'value="', '"'); // c'est un peu trop cablé: ordre et __EVENTARGUMENT='': serait mieux si c'était plus précis // page histoire idhistoire := TextBetween(Value, '__doPostBack(''', ''''); Value := RemainingText; if idhistoire <> '' then begin idhistoire := StringReplace(idhistoire, '$', ':'); idhistoire := '__EVENTTARGET='+ idhistoire + '&__EVENTARGUMENT=&__VIEWSTATE=' + viewstate; end; // page avis de la rédaction idavis := TextBetween(Value, '__doPostBack(''', ''''); Value := RemainingText; if idavis <> '' then begin idavis := StringReplace(idavis, '$', ':'); idavis := '__EVENTTARGET='+ idavis + '&__EVENTARGUMENT=&__VIEWSTATE=' + viewstate; end; // page générique idgenerique := TextBetween(Value, '__doPostBack(''', ''''); Value := RemainingText; if idgenerique <> '' then begin idgenerique := StringReplace(idgenerique, '$', ':'); idgenerique := '__EVENTTARGET='+ idgenerique + '&__EVENTARGUMENT=&__VIEWSTATE=' + viewstate; end; // page anecdote idanecdote := TextBetween(Value, '__doPostBack(''', ''''); if idanecdote <> '' then begin idanecdote := StringReplace(idanecdote, '$', ':'); idanecdote := '__EVENTTARGET='+ idanecdote + '&__EVENTARGUMENT=&__VIEWSTATE=' + viewstate; end; end else begin // url normale (méthode actuelle) // page histoire idhistoire := GetUrlPage(Value, '>L''histoire'); // page avis de la rédaction idavis := GetUrlPage(Value,'>L''avis de la rédaction'); // page générique idgenerique := GetUrlPage(Value,'>Le générique complet'); // page anecdote idanecdote := GetUrlPage(Value,'>L''anecdote'); end; // si certains champs ne doivent pas être valorisés, inutile de lire les pages supplémentaires if not CanSetField(fieldDescription) then idhistoire := ''; if not CanSetField(fieldComments) then idanecdote := ''; if not CanSetField(fieldComments) and (not CanSetField(fieldRating)) then idavis := ''; // pour générique complet // il faut tester 'not' pour acteurs et réalisateur et producteur et durée et année Value := ''; if CanSetField(fieldActors) then Value := 'ok'; if CanSetField(fieldDirector) then Value := 'ok'; if CanSetField(fieldProducer) then Value := 'ok'; if CanSetField(fieldLength) then Value := 'ok'; if CanSetField(fieldYear) then Value := 'ok'; if Value = '' then idgenerique := ''; end; //------------------------------------------------------------------------------ // récupération de l'url d'une sous-page // url := GetUrlPage(texte_contenant_l'url, texte_à_chercher) //------------------------------------------------------------------------------ function GetUrlPage(wholetext, str: string) : string; var id: string; i: integer; begin // l'url est avant le texte cherché i := Pos(str, wholetext); id := left(wholetext, i + length(str)); // et après le dernier '', ''); end; //------------------------------------------------------------------------------ // traitement mode batch //------------------------------------------------------------------------------ procedure MrCinemaBatch; begin SetField(fieldChecked, ''); // init film en traitement case BatchMode of 1: begin // recherche par url MovieName := GetField(fieldUrl); // pas d'url ou autre site, ignorer if (MovieName <> '') and (Pos(MrCinemaUrlFilm, MovieName) > 0) then AnalyzeMoviePageMrCinema(MovieName) else LogMessage('MrCinéma: non traitée url="'+Moviename+'"'); end; 2: begin // recherche par nom + réalisateur MovieName := GetMovieName; if MovieName <> '' then begin initBatchLook; // init paramètres de recherche AnalyzePageMrCinema; end else LogMessage('MrCinéma: non traitée (pas de nom de film)'); end; end; {case} if filmok then begin SetField(fieldChecked, 'x'); // film ok if ((ImportPicture = 2) or (ImportPicture = 3)) then begin // ok pour MrCinéma: rechercher l'affiche Cinéfil // (forcément par nom + réalisateur tant qu'il n'y a pas de 2ème champ url) MovieName := GetMovieName; // relecture if MovieName <> '' then begin initBatchLook; AnalyzePageCinefil; end; end; {import picture} end; {filmok} end; //------------------------------------------------------------------------------ // traitement mode normal //------------------------------------------------------------------------------ procedure MrCinemaNorm; var mname: string; // Input ne peut pas accéder aux variables déclarées dans les units begin // Monsieur cinéma mname := GetMovieName; msgano := 'Entrez le titre du film'; repeat if not Input('MonsieurCinéma.com Import', msgano, mname) or (mname = '') then exit; MovieName := mname; AnalyzePageMrCinema; until filmok; // Cinéfil (si image demandée) if (ImportPicture = 2) or (ImportPicture = 3) then begin MovieName := GetMovieName; // relecture filmok := False; msgano := 'Entrez le titre du film'; repeat AnalyzePageCinefil; if not filmok then begin // page non trouvée ou erreur: on y retourne mname := MovieName; if not Input('Cinéfil.com Import', msgano, mname) or (mname = '') then exit; // non saisie: on sort MovieName := mname; end; until filmok; end; {import picture} end; //------------------------------------------------------------------------------ // c'est ici que ça commence //------------------------------------------------------------------------------ begin if abort = 'o' then exit; // mode batch non confirmé if firstcall <> 'done' then begin // 1er appel: init paramètres firstcall := 'done'; if not CheckVersion(3,5,0) then begin ShowMessage('Ce script requiert une version plus récente de Ant Movie Catalog (au moins la version 3.5.0)'); abort := 'o'; exit; end; calledBy := mrcinema_id; // identifiant appelant batchlogfic := 'c:\amc_MrCinema_batchlog.txt'; // log pour mode batch debug := False; // mode debug on/off debugrep := 'd:\temp\'; // répertoire de stockage des fichiers // récupère les variables user (utilisées plus d'une fois) BatchMode := GetOption('Mode'); FormatTitre := GetOption('FormatTitre'); ImportPicture := GetOption('Image'); if not CanSetPicture then ImportPicture := 0; // champ image non modifiable: inutile de lire // if BatchMode > 0 then // mode batch: confirmer le choix begin initBatchLog; // init log if not ShowWarning(confbatch.Text) then begin AddToLog('mode batch annulé'); abort := 'o'; exit; end; end; end; // c'est parti filmok := False; if BatchMode = 0 then MrCinemaNorm else MrCinemaBatch; end.